package org.jeecg.modules.in.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.constant.WarehouseConstant;
import org.jeecg.modules.basic.basicSkuInfo.entity.BasicSkuInfo;
import org.jeecg.modules.basic.basicSkuInfo.service.IBasicSkuInfoService;
import org.jeecg.modules.in.entity.InOrderDetail;
import org.jeecg.modules.in.entity.InOrderInfo;
import org.jeecg.modules.in.service.IInOrderDetailService;
import org.jeecg.modules.in.service.IInOrderInfoService;
import org.jeecg.modules.in.vo.InOrderInfoPage;
import org.jeecg.modules.inventory.inventoryInfo.entity.InventoryInfo;
import org.jeecg.modules.inventory.inventoryInfo.service.IInventoryInfoService;
import org.jeecg.modules.inventory.reportLabel.entity.ReportLabel;
import org.jeecg.modules.inventory.reportLabel.service.IReportLabelService;
import org.jeecg.modules.pick.entity.PickOrderInfo;
import org.jeecg.modules.pick.service.IPickOrderInfoService;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 入库管理
 * @Author: jeecg-boot
 * @Date: 2024-11-29
 * @Version: V1.0
 */
@Api(tags = "入库管理")
@RestController
@RequestMapping("/in/inOrderInfo")
@Slf4j
public class InOrderInfoController {
    @Autowired
    private IInOrderInfoService inOrderInfoService;
    @Autowired
    private IInOrderDetailService inOrderDetailService;
    @Autowired
    private IBasicSkuInfoService basicSkuInfoService;
    @Autowired
    private IPickOrderInfoService pickOrderInfoService;
    @Autowired
    private IReportLabelService reportLabelService;
    @Autowired
    private IInventoryInfoService inventoryInfoService;

    /**
     * 分页列表查询
     *
     * @param inOrderInfo
     * @param pageNo
     * @param pageSize
     * @param req
     * @return
     */
    @AutoLog(value = "入库管理-分页列表查询")
    @ApiOperation(value = "入库管理-分页列表查询", notes = "入库管理-分页列表查询")
    @GetMapping(value = "/webList")
    public Result<?> queryPageListWeb(InOrderInfo inOrderInfo,
                                      @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                      @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                      HttpServletRequest req) {
        QueryWrapper<InOrderInfo> queryWrapper = QueryGenerator.initQueryWrapper(inOrderInfo, req.getParameterMap());
        queryWrapper.ne("status", WarehouseConstant.EnterWarehouseStatusEnum.DELETE.getCode());
        Page<InOrderInfo> page = new Page<InOrderInfo>(pageNo, pageSize);
        IPage<InOrderInfo> pageList = inOrderInfoService.page(page, queryWrapper);
        return Result.OK(pageList);
    }

    /**
     * 分页列表查询
     *
     * @param inOrderInfo
     * @param source        01：所有任务列表 02：过往任务列表
     * @param pageNo
     * @param pageSize
     * @param req
     * @return
     */
    @AutoLog(value = "理货管理-手持分页列表查询")
    @ApiOperation(value = "理货管理-手持分页列表查询", notes = "理货管理-手持分页列表查询")
    @GetMapping(value = "/appList")
    public Result<?> queryPageListApp(InOrderInfo inOrderInfo,
                                      @RequestParam(name = "source") String source,
                                      @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                      @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                      HttpServletRequest req) {
        QueryWrapper<InOrderInfo> queryWrapper = QueryGenerator.initQueryWrapper(inOrderInfo, req.getParameterMap());
        queryWrapper.ne("status", WarehouseConstant.EnterWarehouseStatusEnum.DELETE.getCode());
        if (Objects.equals(source, "01")) {
            queryWrapper.eq("status", WarehouseConstant.EnterWarehouseStatusEnum.RELEASE_END.getCode());
        } else if (Objects.equals(source, "02")) {
            LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
            queryWrapper.eq("execute_name", sysUser.getUsername());
            queryWrapper.ne("status", WarehouseConstant.EnterWarehouseStatusEnum.DELETE.getCode());
        }
        Page<InOrderInfo> page = new Page<>(pageNo, pageSize);
        IPage<InOrderInfo> pageList = inOrderInfoService.page(page, queryWrapper);
        return Result.OK(pageList);
    }

    /**
     * 添加
     *
     * @param inOrderPage 入库单对象
     * @return
     */
    @AutoLog(value = "入库管理-添加入库单")
    @ApiOperation(value = "入库管理-添加入库单", notes = "入库管理-添加入库单")
    @PostMapping(value = "/add")
    public Result<?> add(@RequestBody InOrderInfoPage inOrderPage) {
        // 字段校验
        this.checkColumns(inOrderPage);

        InOrderInfo inOrder = new InOrderInfo();
        BeanUtils.copyProperties(inOrderPage, inOrder);
        inOrderInfoService.saveWarehousingEntry(inOrder, inOrderPage.getInOrderDetailList());
        return Result.OK();
    }

    /**
     * 编辑
     *
     * @param inOrderPage 入库单对象
     * @return
     */
    @AutoLog(value = "入库管理-编辑入库单")
    @ApiOperation(value = "入库管理-编辑入库单", notes = "入库管理-编辑入库单")
    @PutMapping(value = "/edit")
    public Result<?> edit(@RequestBody InOrderInfoPage inOrderPage) {
        // 字段校验
        Assert.isTrue(Objects.equals(inOrderPage.getStatus(), WarehouseConstant.EnterWarehouseStatusEnum.CREATE_END.getCode()), "发布后的入库单不支持修改！");
        this.checkColumns(inOrderPage);

        InOrderInfo inOrder = new InOrderInfo();
        BeanUtils.copyProperties(inOrderPage, inOrder);
        inOrderInfoService.saveWarehousingEntry(inOrder, inOrderPage.getInOrderDetailList());
        return Result.OK();
    }

    /**
     * 字段校验
     *
     * @param inOrderPage
     */
    private void checkColumns(InOrderInfoPage inOrderPage) {
        Assert.isTrue(StringUtils.isNotBlank(inOrderPage.getContainerNo()), "请输入集装箱号！");
        Assert.notNull(inOrderPage.getInOrderTime(), "请选择入库时间！");
        Assert.notNull(inOrderPage.getSkuType(), "请选择品番类型！");
        Assert.notEmpty(inOrderPage.getInOrderDetailList(), "请填写入库明细！");
        long nullCount = inOrderPage.getInOrderDetailList().stream().filter(data -> StringUtils.isBlank(data.getSkuCode()) || data.getBoxQuantity() == null).count();
        Assert.isTrue(nullCount == 0, "品番编码与入库数量必须填写！");

        int repeatCount = inOrderInfoService.count(new LambdaQueryWrapper<InOrderInfo>()
                .ne(StringUtils.isNotBlank(inOrderPage.getId()), InOrderInfo::getId, inOrderPage.getId())
                .eq(InOrderInfo::getInOrderCode, inOrderPage.getInOrderCode()));
        Assert.isTrue(repeatCount == 0, "订单号已存在！");
    }

    @AutoLog(value = "入库管理-发布入库单")
    @ApiOperation(value = "入库管理-发布入库单", notes = "编辑入库单，补充入库信息后发布，才能领取")
    @PostMapping("/release")
    public Result<?> release(@RequestParam(name = "id") String id) {
        inOrderInfoService.releaseWarehousingEntry(id);
        return Result.OK();
    }

    @AutoLog(value = "入库管理-领取任务")
    @ApiOperation(value = "入库管理-领取任务", notes = "入库管理-领取任务")
    @PostMapping("/receive")
    @Transactional(rollbackFor = Exception.class)
    public Result<?> receive(@RequestParam(name = "id") String id) {
        Assert.isTrue(StringUtils.isNotBlank(id), "请选择要领取的入库单任务！");
        // todo：先不做领取的角色限制

        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        // 校验当前登录用户账号下是否有正在执行的任务。业务逻辑：用户账号不允许更改
        int doingCount = inOrderInfoService.count(new LambdaQueryWrapper<InOrderInfo>()
                .eq(InOrderInfo::getExecuteName, loginUser.getUsername())
                .eq(InOrderInfo::getStatus, WarehouseConstant.EnterWarehouseStatusEnum.RECEIVE_END.getCode()));
        Assert.isTrue(doingCount == 0, "您还有未执行完成的任务，请执行任务后再领取新的任务");

        InOrderInfo inOrderInfo = inOrderInfoService.getById(id);
        inOrderInfo.setStatus(WarehouseConstant.EnterWarehouseStatusEnum.RECEIVE_END.getCode());
        inOrderInfo.setExecuteName(loginUser.getUsername());
        inOrderInfo.setExecuteTime(new Date());
        inOrderInfoService.updateById(inOrderInfo);

        return Result.OK();
    }

    /**
     * @param
     * @return
     */
    @AutoLog(value = "入库操作-扫码入库")
    @ApiOperation(value = "入库操作-扫码入库", notes = "入库操作-扫码入库")
    @PostMapping(value = "/scanCode")
    @Transactional(rollbackFor = Exception.class)
    public Result<?> scanCode(@RequestBody JSONObject jsonObject) {
        String inOrderId = jsonObject.getString("inOrderId");
        String labelNumber = jsonObject.getString("labelNumber");
        String roadCode = jsonObject.getString("roadCode");
        Assert.isTrue(StringUtils.isNotBlank(inOrderId), "缺少必要参数inOrderId！");
        Assert.isTrue(StringUtils.isNotBlank(labelNumber), "缺少必要参数labelNumber！");
        Assert.isTrue(StringUtils.isNotBlank(roadCode), "缺少必要参数roadCode！");

        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

        InOrderInfo inOrderInfo = inOrderInfoService.getById(inOrderId);
        Assert.notNull(inOrderInfo, "查询系统中不存在对应的入库单，入库单数据异常，请联系管理员！");
        Assert.isTrue(Objects.equals(inOrderInfo.getExecuteName(), loginUser.getUsername()), "请勿执行他人的入库任务！");
        Assert.isTrue(Objects.equals(inOrderInfo.getStatus(), WarehouseConstant.EnterWarehouseStatusEnum.RECEIVE_END.getCode()), "入库单非进行中状态，无法入库，请联系管理员！");
        List<InOrderDetail> inOrderDetailList = inOrderDetailService.list(new LambdaQueryWrapper<InOrderDetail>()
                .eq(InOrderDetail::getInOrderId, inOrderInfo.getId()));
        Assert.notEmpty(inOrderDetailList, "查询系统中不存在入库单对应的入库详情，入库单数据异常，请联系管理员！");

        // 获取本次要入库的货垛
        String stackCode = null;
        for (InOrderDetail inOrderDetail : inOrderDetailList) {
            if (labelNumber.contains(inOrderDetail.getStackCode())) {
                stackCode = inOrderDetail.getStackCode();
            }
        }
        Assert.notNull(stackCode, "扫描的二维码不是当前入库任务中的货垛码，请检查后重试！");

        int otherOrderCount = reportLabelService.count(new LambdaQueryWrapper<ReportLabel>()
                .eq(ReportLabel::getWarehouseCode, WarehouseConstant.WarehouseTypeEnum.ROAD.getCode())
                .gt(ReportLabel::getAvailableBoxQuantity, 0)
                .ne(ReportLabel::getInOrderCode, inOrderInfo.getInOrderCode()));
        Assert.isTrue(otherOrderCount == 0, "当前货道内还存在其它订单的货物，无法入库！");
        int enterEndCount = reportLabelService.count(new LambdaQueryWrapper<ReportLabel>()
                .eq(ReportLabel::getWarehouseCode, WarehouseConstant.WarehouseTypeEnum.ROAD.getCode())
                .eq(ReportLabel::getStackCode, stackCode)
                .eq(ReportLabel::getInOrderCode, inOrderInfo.getInOrderCode()));
        Assert.isTrue(enterEndCount == 0, "当前扫描的货垛已入库完成，请勿重复入库！");
        int otherOrderLabelNumberCount = reportLabelService.count(new LambdaQueryWrapper<ReportLabel>()
                .eq(ReportLabel::getLabelNumber, labelNumber)
                .ne(ReportLabel::getInOrderCode, inOrderInfo.getInOrderCode()));
        Assert.isTrue(otherOrderLabelNumberCount == 0, "查询后台数据中标签号已存在，无法使用，请重新生成货垛码使用！");
        // 如果是理货任务生成的入库单，需要校验标签号扫的对不对
        PickOrderInfo pickOrderInfo = pickOrderInfoService.getOne(new LambdaQueryWrapper<PickOrderInfo>()
                .eq(PickOrderInfo::getPickOrderCode, inOrderInfo.getInOrderCode())
                .eq(PickOrderInfo::getStatus, WarehouseConstant.PickWarehouseStatusEnum.ENTER_ORDER.getCode()));
        if (null != pickOrderInfo) {
            int pickLabelNumberCount = reportLabelService.count(new LambdaQueryWrapper<ReportLabel>()
                    .eq(ReportLabel::getWarehouseCode, WarehouseConstant.WarehouseTypeEnum.PICK.getCode())
                    .eq(ReportLabel::getLabelNumber, labelNumber)
                    .eq(ReportLabel::getInOrderCode, inOrderInfo.getInOrderCode()));
            Assert.isTrue(pickLabelNumberCount > 0, "当前扫描的标签号在系统中不存在，请重新扫描，如问题依旧请联系管理员！");
        }

        Map<String, List<InOrderDetail>> enterMap = inOrderDetailList.stream().filter(data -> labelNumber.contains(data.getStackCode())).collect(Collectors.groupingBy(InOrderDetail::getSkuCode));
        for (String skuCode : enterMap.keySet()) {
            // 新增与编辑的时候已经做了品番编码校验，品番编码一定存在！
            BasicSkuInfo skuInfo = basicSkuInfoService.list(new LambdaQueryWrapper<BasicSkuInfo>().eq(BasicSkuInfo::getSkuCode, skuCode)).get(0);

            // 货垛内当前品番的总箱数
            List<InOrderDetail> enterTaskDetailList = enterMap.get(skuCode);
            int boxQuantity = enterTaskDetailList.stream().mapToInt(InOrderDetail::getBoxQuantity).sum();

            // 理货任务生成的入库单，需要更新理货区的库存信息
            if (null != pickOrderInfo) {
                // report_label 理货区数据存储逻辑：以标签号、货垛码、品番编码与理货订单号作为唯一。
                reportLabelService.update(
                        new ReportLabel()
                                .setAvailableBoxQuantity(0),
                        new LambdaQueryWrapper<ReportLabel>()
                                .eq(ReportLabel::getWarehouseCode, WarehouseConstant.WarehouseTypeEnum.PICK.getCode())
                                .eq(ReportLabel::getLabelNumber, labelNumber)
                                .eq(ReportLabel::getStackCode, stackCode)
                                .eq(ReportLabel::getSkuCode, skuCode)
                                .eq(ReportLabel::getInOrderCode, inOrderInfo.getInOrderCode()));

                // inventory_info 理货区数据存储逻辑：以品番编码作为唯一(不存储货架编码、货格编码与货垛码)。
                InventoryInfo pickInventoryInfo = inventoryInfoService.getOne(new LambdaQueryWrapper<InventoryInfo>()
                        .eq(InventoryInfo::getWarehouseCode, WarehouseConstant.WarehouseTypeEnum.PICK.getCode())
                        .eq(InventoryInfo::getSkuCode, skuCode));
                if (null != pickInventoryInfo) {
                    Assert.isTrue(pickInventoryInfo.getInventoryBoxQuantity() >= boxQuantity,
                            "品番编码：【%s】在理货区剩余库存箱数【%s】箱，本次需入库【%s】箱，库存不足，无法入库！", skuCode, pickInventoryInfo.getInventoryBoxQuantity(), boxQuantity);
                    pickInventoryInfo.setInventoryBoxQuantity(pickInventoryInfo.getInventoryBoxQuantity() - boxQuantity);
                    if (pickInventoryInfo.getInventoryBoxQuantity() == 0 && pickInventoryInfo.getAvailableBoxQuantity() == 0) {
                        inventoryInfoService.removeById(pickInventoryInfo.getId());
                    } else {
                        inventoryInfoService.updateById(pickInventoryInfo);
                    }
                }
            }

            // report_label 货道区数据存储逻辑：以货道编码、标签号、货垛码与品番编码作为唯一。
            ReportLabel reportLabel = new ReportLabel();
            reportLabel.setWarehouseCode(WarehouseConstant.WarehouseTypeEnum.ROAD.getCode());
            reportLabel.setRoadCode(roadCode);
            reportLabel.setLabelNumber(labelNumber);
            reportLabel.setStackCode(stackCode);
            reportLabel.setSkuCode(skuCode);
            reportLabel.setInventoryBoxQuantity(boxQuantity);
            reportLabel.setAvailableBoxQuantity(boxQuantity);
            reportLabel.setSkuType(skuInfo.getSkuType());
            reportLabel.setInOrderCode(inOrderInfo.getInOrderCode());
            reportLabel.setEnterDate(inOrderInfo.getInOrderTime());
            reportLabel.setStackingDate(new Date());
            reportLabel.setContainerNo(inOrderInfo.getContainerNo());
            reportLabel.setOutOrderCode(null);
            reportLabelService.save(reportLabel);

            // inventory_info 货道区数据存储逻辑：以货道编码、货垛码与品番编码作为唯一（已校验一个货道内只放一个订单货物，不会出现一个货道内多个货垛的货垛码一致）。
            InventoryInfo inventoryInfo = new InventoryInfo();
            inventoryInfo.setWarehouseCode(WarehouseConstant.WarehouseTypeEnum.ROAD.getCode());
            inventoryInfo.setRoadCode(roadCode);
            inventoryInfo.setStackCode(stackCode);
            inventoryInfo.setSkuCode(skuCode);
            inventoryInfo.setInventoryBoxQuantity(boxQuantity);
            inventoryInfo.setAvailableBoxQuantity(boxQuantity);
            inventoryInfo.setEnterDate(new Date());
            inventoryInfo.setOutOrderCode(null);
            inventoryInfoService.save(inventoryInfo);
        }

        // 校验所有任务是否完成
        Set<String> orderStackCodeSet = inOrderDetailList.stream().map(InOrderDetail::getStackCode).collect(Collectors.toSet());
        List<ReportLabel> reportLabelList = reportLabelService.list(new LambdaQueryWrapper<ReportLabel>()
                .eq(ReportLabel::getWarehouseCode, WarehouseConstant.WarehouseTypeEnum.ROAD.getCode())
                .eq(ReportLabel::getInOrderCode, inOrderInfo.getInOrderCode()));
        Set<String> reportStackCodeSet = reportLabelList.stream().map(ReportLabel::getStackCode).collect(Collectors.toSet());
        if (reportStackCodeSet.equals(orderStackCodeSet)) {
            inOrderInfo.setStatus(WarehouseConstant.PickWarehouseStatusEnum.EXECUTE_END.getCode());
            inOrderInfo.setEndTime(new Date());
            inOrderInfoService.updateById(inOrderInfo);
        }

        return Result.OK(inOrderInfo.getStatus());
    }

    /**
     * 通过id删除
     *
     * @param id
     * @return
     */
    @AutoLog(value = "入库管理-通过id删除")
    @ApiOperation(value = "入库管理-通过id删除", notes = "入库管理-通过id删除")
    @DeleteMapping(value = "/delete")
    public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
        inOrderInfoService.delMain(id);
        return Result.OK("删除成功!");
    }

    /**
     * 批量删除
     *
     * @param ids
     * @return
     */
    @AutoLog(value = "入库管理-批量删除")
    @ApiOperation(value = "入库管理-批量删除", notes = "入库管理-批量删除")
    @DeleteMapping(value = "/deleteBatch")
    public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
        this.inOrderInfoService.delBatchMain(Arrays.asList(ids.split(",")));
        return Result.OK("批量删除成功！");
    }

    /**
     * 通过id查询
     *
     * @param id
     * @return
     */
    @AutoLog(value = "入库管理-通过id查询")
    @ApiOperation(value = "入库管理-通过id查询", notes = "入库管理-通过id查询")
    @GetMapping(value = "/queryById")
    public Result<?> queryById(@RequestParam(name = "id", required = true) String id) {
        InOrderInfo inOrderInfo = inOrderInfoService.getById(id);
        if (inOrderInfo == null) {
            return Result.error("未找到对应数据");
        }
        return Result.OK(inOrderInfo);
    }

    /**
     * 通过id查询
     *
     * @param id
     * @return
     */
    @AutoLog(value = "入库单详情通过主表ID查询")
    @ApiOperation(value = "入库单详情主表ID查询", notes = "入库单详情-通主表ID查询")
    @GetMapping(value = "/queryInOrderDetailByMainId")
    public Result<?> queryInOrderDetailListByMainId(@RequestParam(name = "id", required = true) String id) {
        List<InOrderDetail> inOrderDetailList = inOrderDetailService.selectByMainId(id);
        return Result.OK(inOrderDetailList);
    }

    /**
     * 导出excel
     *
     * @param request
     * @param inOrderInfo
     */
    @RequestMapping(value = "/exportXls")
    public ModelAndView exportXls(HttpServletRequest request, InOrderInfo inOrderInfo) {
        // Step.1 组装查询条件查询数据
        QueryWrapper<InOrderInfo> queryWrapper = QueryGenerator.initQueryWrapper(inOrderInfo, request.getParameterMap());
        queryWrapper.ne("status", WarehouseConstant.EnterWarehouseStatusEnum.DELETE.getCode());
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

        //Step.2 获取导出数据
        List<InOrderInfo> queryList = inOrderInfoService.list(queryWrapper);
        // 过滤选中数据
        String selections = request.getParameter("selections");
        List<InOrderInfo> inOrderInfoList = new ArrayList<InOrderInfo>();
        if (oConvertUtils.isEmpty(selections)) {
            inOrderInfoList = queryList;
        } else {
            List<String> selectionList = Arrays.asList(selections.split(","));
            inOrderInfoList = queryList.stream().filter(item -> selectionList.contains(item.getId())).collect(Collectors.toList());
        }

        // Step.3 组装pageList
        List<InOrderInfoPage> pageList = new ArrayList<InOrderInfoPage>();
        for (InOrderInfo main : inOrderInfoList) {
            InOrderInfoPage vo = new InOrderInfoPage();
            BeanUtils.copyProperties(main, vo);
            List<InOrderDetail> inOrderDetailList = inOrderDetailService.selectByMainId(main.getId());
            vo.setInOrderDetailList(inOrderDetailList);
            pageList.add(vo);
        }

        // Step.4 AutoPoi 导出Excel
        ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
        mv.addObject(NormalExcelConstants.FILE_NAME, "入库管理列表");
        mv.addObject(NormalExcelConstants.CLASS, InOrderInfoPage.class);
        mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("入库管理数据", "导出人:" + sysUser.getRealname(), "入库管理"));
        mv.addObject(NormalExcelConstants.DATA_LIST, pageList);
        return mv;
    }

    /**
     * 通过excel导入数据
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
    public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            MultipartFile file = entity.getValue();// 获取上传文件对象
            ImportParams params = new ImportParams();
            params.setTitleRows(2);
            params.setHeadRows(1);
            params.setNeedSave(true);
            try {
                List<InOrderInfoPage> list = ExcelImportUtil.importExcel(file.getInputStream(), InOrderInfoPage.class, params);
                for (InOrderInfoPage page : list) {
                    InOrderInfo po = new InOrderInfo();
                    BeanUtils.copyProperties(page, po);
                    inOrderInfoService.saveWarehousingEntry(po, page.getInOrderDetailList()
                            .stream().filter(data -> StringUtils.isNotBlank(data.getStackCode()) && StringUtils.isNotBlank(data.getSkuCode()) && null != data.getBoxQuantity())
                            .collect(Collectors.toList()));
                }
                return Result.OK("文件导入成功！数据行数:" + list.size());
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                return Result.error("文件导入失败:" + e.getMessage());
            } finally {
                try {
                    file.getInputStream().close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return Result.OK("文件导入失败！");
    }

}
